package com.jufa_3.service.impl;

import com.jufa_3.common.PayUtil;
import com.jufa_3.common.RequestTool;
import com.jufa_3.common.Signature;
import com.jufa_3.config.WeiXinConfig;
import com.jufa_3.dto.OrderReturnInfo;
import com.jufa_3.dto.PayInfo;
import com.jufa_3.dto.QueryReturnInfo;
import com.jufa_3.dto.SignInfo;
import com.jufa_3.service.PayService;
import com.thoughtworks.xstream.XStream;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

@Service
public class PayServiceImpl implements PayService {


    /**发起支付
     * @param payInfo
     * @return
     */
    public  Map<String, String> payment(PayInfo payInfo) {
        // 生成签名
        String result = null;
        try {
            payInfo.setSign(Signature.getSign(payInfo));
            result = RequestTool.sendPost("https://api.mch.weixin.qq.com/pay/unifiedorder", payInfo);
        } catch (IllegalAccessException | IOException e) {
            e.printStackTrace();
        }
        XStream xStream = new XStream();
        xStream.alias("xml", OrderReturnInfo.class);
        OrderReturnInfo returnInfo = (OrderReturnInfo) xStream.fromXML(result);
        // 二次签名
        if ("SUCCESS".equals(returnInfo.getReturn_code()) && returnInfo.getReturn_code().equals(returnInfo.getResult_code())) {
            SignInfo signInfo = new SignInfo();
            signInfo.setAppId(payInfo.getAppid());
            long time = System.currentTimeMillis() / 1000;
            signInfo.setTimeStamp(String.valueOf(time));
            signInfo.setNonceStr(payInfo.getNonce_str());
            signInfo.setRepay_id("prepay_id=" + returnInfo.getPrepay_id());
            signInfo.setSignType("MD5");
            // 生成签名
            String paySign = null;
            try {
                paySign = Signature.getSign(signInfo);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            Map<String, String> payReturnInfo = new HashMap<>();
            payReturnInfo.put("timeStamp", signInfo.getTimeStamp());
            payReturnInfo.put("nonceStr", signInfo.getNonceStr());
            payReturnInfo.put("package", signInfo.getRepay_id());
            payReturnInfo.put("signType", signInfo.getSignType());
            payReturnInfo.put("out_trade_no",payInfo.getOut_trade_no());
            payReturnInfo.put("paySign", paySign);
            return payReturnInfo;
        }
        return null;
    }

    /**提取支付回调参数
     * @param request
     * @return
     * @throws Exception
     */
    public Map<String, String> notifyDecode(HttpServletRequest request) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) { sb.append(line);}
        br.close();
        String notityXml = sb.toString();  // sb为微信返回的xml
        return PayUtil.doXMLParse(notityXml);
    }

    /**验证签名
     * @param map
     * @return
     */
    public boolean verifySign(Map<String, String> map) {
        Map<String, String> validParams = PayUtil.paraFilter(map);  // 回调验签时需要去除sign和空值参数
        String validStr = PayUtil.createLinkString(validParams);    // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        String sign = PayUtil.sign(validStr, WeiXinConfig.getPublic_Key(),"utf-8").toUpperCase();//拼装生成服务器端验证的签名
        return sign.equals(map.get("sign"));
    }

    /**查询支付结果
     *
     * @param OutTradeNo
     * @return
     */
    public QueryReturnInfo orderQuery(String OutTradeNo) {
        Map<String, Object> map = new HashMap<>();
        try {
            PayInfo order = new PayInfo();
            order.setOut_trade_no(OutTradeNo);
            String sign = Signature.getSign(order);
            order.setSign(sign);
            String result = RequestTool.sendPost(WeiXinConfig.getQuery_url(), order);
            XStream xStream = new XStream();
            xStream.alias("xml", QueryReturnInfo.class);
            QueryReturnInfo returnInfo = (QueryReturnInfo) xStream.fromXML(result);
            return returnInfo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
